package net.chat.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.chat.Forum;
import net.chat.Message;
import net.chat.User;
import net.chat.server.ChatServer;
import net.chat.utils.Util;

/**
`* The MsgServlet is used to service requests relating to forums.
 * @author Prabhat
 * Implemented doGet to service 'receive' requests from the client
 * Implemented doPost to service 'send' requests from the client
 */
public class MsgServlet extends HttpServlet {

    private ChatServer server;

    // constructor
    public MsgServlet() {
        server = ChatServer.getInstance();
    }

    /**
     * Handles GET requests from client. It checks for any new message and send
     * to the client. It waits until new message arrives before sending back the
     * response (it holds the connection).
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        long timeBefore = new Date().getTime(); // in milliseconds

        String userId = request.getParameter("uid");
        String forumId = request.getParameter("fid");

        int uid = new Integer(userId).intValue();
        int fid = new Integer(forumId).intValue();

        User user = server.getUser(uid);
        Forum forum = server.getForum(fid);

        if (forum != null && user != null) {

            String t = request.getParameter("timeout");
            int timeout = Util.AJAX_LONG_LIVE_TIMEOUT;
            if (t != null) {
                timeout = new Integer(t).intValue();
            }
            // ajax timeout is set to 5 mins
            // if msg arrives after 5 mins, it cannot be delivered in this request
            // next request will handle it

            response.setContentType("text/html;charset=UTF-8");
            PrintWriter out = response.getWriter();

            // the logic below is:
            // 1. if user has been inactive for the max time, break loop and return
            //    'redirect' in the response. client needs to redirect to the forums
            //    page.
            // 2. if new message is taking longer than the timeout, break loop and
            //    return 'timeout' in the response. client needs to establish another
            //    connection.
            // 3. if no new message arrives while the other conditions hold, wait for
            //    a few seconds and check again

            try {
                long timeAfter; // in milliseconds
                long diff;

                long lastChatTime;
                long timeNow;

                while (true) {

                    lastChatTime = user.getLastChat().getTime();
                    timeNow = new Date().getTime();

                    long diffInMin = ((timeNow - lastChatTime) / 1000) / 60;

                    if (diffInMin > Util.MAX_INACTIVE_MIN) {
                        forum.leave(user);
                        out.print("redirect");
                        out.flush();
                        break;
                    }

                    timeAfter = new Date().getTime();
                    diff = timeAfter - timeBefore;

                    if (diff > timeout) {
                        out.print("timeout");
                        out.flush();
                        break;
                    }

                    List<Message> newMessages = forum.getNewMessages();
                    if (newMessages.size() > 0) {
                        Message m = newMessages.get(0); // get the first message
                        if (m.deliver(user)) {
                            String msgStr = m.getMid() + ". Sent " + m.getSent()
                                    + " by " + m.getFromUser().getFname() + "<br/>"
                                    + m.getMessage();
                            out.print(msgStr);
                            out.flush();
                            break;
                        }
                    }
                    // check for new messages every 2 secs
                    Thread.sleep(2 * 1000);
                }
            } catch (InterruptedException ex) {
                Logger.getLogger(MsgServlet.class.getName()).log(Level.SEVERE, null, ex);
            } finally {
                out.close();
            }
        }
    }

    /**
     * Handles POST requests from client. Messages typed in the textbox are posted
     * and handled here. The message is added to the forum list of new messages and
     * a 'success' is returned back to the client.
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String userId = request.getParameter("uid");
        String forumId = request.getParameter("fid");
        String msg = request.getParameter("msg");

        int uid = new Integer(userId).intValue();
        int fid = new Integer(forumId).intValue();
        User user = server.getUser(uid);
        Forum forum = server.getForum(fid);

        if (forum != null && user != null) {
            Message m = new Message(msg, user);
            forum.newMessage(m);
            user.setLastChat(new Date());

            response.setContentType("text/html;charset=UTF-8");
            PrintWriter out = response.getWriter();
            try {
                out.print("success");
                out.flush();
            } finally {
                out.close();
            }
        }
    }
}
